/** 
 * 
 * Copyright (C) 2010-2012  Nicolas Hernandez
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *     http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package fr.univnantes.lina.uima.connectors.ftb;


import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;


//import fr.univnantes.lina.java.util.HashMapStringKeyComparatorByIntegerValue;
import fr.univnantes.lina.java.util.CollectionUtilities;
import fr.univnantes.lina.java.util.DateUtilities;
import fr.univnantes.lina.java.util.XMLUtilities;
import fr.univnantes.lina.uima.common.AnnotationUtils;

import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;


//import fr.univnantes.lina.uima.connectors.ftb.MultiWordExpression;


/**
 * Revise the FTB
 * 
 * Run with arguments
 * /media/MyPassport/workspace/data/input/doc/ftb-tagged/lmf7as1ep.cat.utf8.xml /tmp/domoutfile-light-revised.xml
 * /media/MyPassport/workspace/data/input/doc/ftb-tagged/lmf7ad1co.aa.utf8.xml /tmp/domoutfile-light-revised.xml
 * /media/MyPassport/workspace/data/input/doc/ftb-tagged2/lmf7aj2.xml.aa.cat.utf8.xml /tmp/domoutfile-light-revised.xml
 * /media/MyPassport/workspace/data/processed/FrenchTreebank/ftb-v120100/corpus-tagged-utf8/lmf7ak1ep.indent.utf8.xml /tmp/domoutfile-light-revised.xml
 * 
 * /media/MyPassport/workspace/data/processed/FrenchTreebank/ftb-v120100/corpus-tagged-utf8-oneFile/ftb120100-tagged-utf8.xml /tmp/domoutfile-revised.xml
 *
 *TODO to improve the script regarder les cas qui semblent avoir un pb
 *  less /tmp/domoutfile-revised.xml | grep amalgame | sort | uniq | less
 *  less /tmp/domoutfile-revised.xml # search clues
 *  less /media/MyPassport/workspace/data/processed/FrenchTreebank/ftb-v120100/corpus-tagged-utf8-oneFile/ftb120100-tagged-utf8.xml  
# search clues 

 * optimization:
 * -Dorg.apache.xml.dtm.DTMManager=org.apache.xml.dtm.ref.DTMManagerDefault -Xmx1536m
 * <p>
 * good java dom tutorial: http://www.exampledepot.com/egs/org.w3c.dom/pkg.html 
 * </p>
 * 
 * @author Nicolas Hernandez
 */
public class FTBProcessRevision {

	private String infileName = "";
	private String outfileName = "";
	private Document domDoc = null;

	final String catAttrName  = "cat";
	final String catintAttrName  = "catint";
	final String subcatAttrName  = "subcat";
	final String lemmaAttrName  = "lemma";
	final String mphAttrName  = "mph";
	final String compoundAttrName  = "compound";
	final String eeAttrName  = "ee";
	final String eiAttrName  = "ei";

	final String wordElement  ="w";

	final String prepositionTag  ="P";
	final String determinerTag  ="D";

	/*
	 * import/export
	 */



	/**
	 * Local problems require ad hoc fix 
	 * TODO Dom is simpler than SAX but in order to factor several bugs
	 * one for loop and one xpath //w (will consider single word, multi word and part of word 
	 * then rewrite the xpath conditions of each bug into conditional java codes
	 * @param domDoc
	 */
	public void adhocFix (Node domNode) {

		int adhocFixCounter = 0;


		NodeList nodeList  = FTBXMLVariousDOMHandler.getNodeListFromXPathExpression(domDoc,
				"//w");

		Set<String> deTextContentSet = new HashSet<String>();
		deTextContentSet.add("d'");	
		deTextContentSet.add("de");	
		deTextContentSet.add("des");
		deTextContentSet.add("du");	
		deTextContentSet.add("des");	
		deTextContentSet.add("du");

		Set<String> toutTextContentSet = new HashSet<String>();
		toutTextContentSet.add("tous");	
		toutTextContentSet.add("tout");	
		toutTextContentSet.add("toute");
		toutTextContentSet.add("toutes");	

		Map<String,String> tout2le = new HashMap<String,String>();
		tout2le.put("ms", "le");
		tout2le.put("tout", "le");
		tout2le.put("fs", "la");
		tout2le.put("toute", "la");
		tout2le.put("mp", "les");
		tout2le.put("tous", "les");
		tout2le.put("fp", "les");
		tout2le.put("toutes", "les");

		for(int i=0; (i < nodeList.getLength()); i++) {
			if (nodeList.item(i) instanceof Element) {
				Element e = (Element) nodeList.item(i);
				String textContent = "";

				/* <PRE>
				 * <w lemma="à" ei="NCms" ee="N-C-ms" cat="N" subcat="C" mph="ms">Au</w>
				 * <w lemma="le" ei="Dms" ee="D-def-ms" cat="D" subcat="def" mph="ms"/>
				 * <w lemma="Cameroun" ei="NPms" ee="N-P-ms" cat="N" subcat="P" mph="ms">Cameroun</w>
				 * </PRE>
				 * <PRE>
				 * <w lemma="à" ei="NCms" ee="N-C-ms" cat="N" subcat="C" mph="ms">Au</w>
				 * <w lemma="le" ei="Dms" ee="D-def-ms" cat="D" subcat="def" mph="ms"/>
				 * <w lemma="Maghreb" ei="NPms" ee="N-P-ms" cat="N" subcat="P" mph="ms">Maghreb</w>
				 * </PRE>
				 * //w[@cat='N' and normalize-space(.)='Au']
				 * both should be changed into  cat="P" ee="P" ei="P" lemma="à"
				 */		
				if (e.getAttribute(catAttrName).equalsIgnoreCase("N") && e.getTextContent().equals("Au")) {
					e.setAttribute(catAttrName, prepositionTag);
					e.setAttribute(eeAttrName, prepositionTag);
					e.setAttribute(eiAttrName, prepositionTag);
					e.removeAttribute(subcatAttrName);
					e.removeAttribute(mphAttrName);
					adhocFixCounter++;
				}

				/* cas de composé discontinu...
				 * <w lemma="disposer" ei="VP3s" ee="V--P3s" cat="V" subcat="" mph="P3s">dispose</w>
		<w lemma="-" ei="PONCTW" ee="PONCT-W" cat="PONCT" subcat="W">-</w>
		<w compound="yes" lemma="grâce à" ei="P" ee="P" cat="P" next="3">grâce</w>
		<w lemma="notamment" ei="ADV" ee="ADV" cat="ADV">notamment</w>
		<w compound="yes" lemma="grâce à" ei="P" ee="P" cat="P" prev="1">au</w>
		<w lemma="le" ei="Dms" ee="D-def-ms" cat="D" subcat="def" mph="ms"/>
		<w lemma="contrat" ei="NCms" ee="N-C-ms" cat="N" subcat="C" mph="ms">contrat</w>
		<w lemma="de" ei="P" ee="P" cat="P">des</w>
		<w lemma="le" ei="Dfp" ee="D-def-fp" cat="D" subcat="def" mph="fp"/>
		<w lemma="frégate" ei="NCfp" ee="N-C-fp" cat="N" subcat="C" mph="fp">frégates</w>
ou bien 
<w compound="yes" lemma="par de" ei="P" ee="P" cat="P">par</w>

				we have to keep the word but
				remove the compound attribute to compounds which do not embed w element and contain only textContent
				 */
				else 	if (!e.getAttribute(compoundAttrName).equalsIgnoreCase("") && e.getElementsByTagName(wordElement).getLength() == 0) {
					//System.out.println("Debug: "+e.getTextContent());
					e.removeAttribute(compoundAttrName);
					adhocFixCounter++;
				}

				/*
				<w cat="V" ee="V--W" ei="VW" lemma="provoquer" mph="W" subcat="">provoquer</w>
				<w compound="yes" cat="D" ee="D-ind-fp" ei="Dfp" lemma="de les" mph="fp" subcat="ind">des       <w catint="D"/>
				        <w catint="D"/>
				</w>
				<w cat="N" ee="N-C-fp" ei="NCfp" lemma="trêve" mph="fp" subcat="C">trêves</w>
ou bien

				<w lemma="un" ei="Dmp" ee="D-ind-mp" cat="D" subcat="ind" mph="mp">
					<w cat="D">des</w>
					<w cat="D"/>
				</w>
				<w lemma="éclairagiste" ei="NCmp" ee="N-C-mp" cat="N" subcat="C" mph="mp">éclairagistes</w>

				a compound with or not compound attribute which contains only one not empty w 
				we remove the empty element and if it exists a not empty element we add this text content to the compound and remove this node
				and the compound attribute

				 */
				else if (!(textContent = isCompoundWithOnlyDeterminersAndEmptyElements(e)).equalsIgnoreCase("")) {	
					NodeList eChildrenNodeList = e.getChildNodes();
					//System.out.println("BEFORE----------------------- e.getNodeValue() "+ e.getNodeValue()+ " textContent "+textContent);
					//XMLUtilities.displayDomTree(e);
					for(int k=0; (k < eChildrenNodeList.getLength()); k++) {
						if (eChildrenNodeList.item(k) instanceof Element) {
							//System.out.println("Debug: remove "+eChildrenNodeList.item(k).getNodeValue());

							Element eChildElement = (Element) eChildrenNodeList.item(k);
							e.removeChild(eChildElement);
						}
						//eChildrenNodeList.item(k).getParentNode().removeChild(eChildrenNodeList.item(k));
					}
					e.setTextContent(textContent.trim()) ;
					e.removeAttribute(compoundAttrName);
					textContent = "";
					adhocFixCounter++;	
					//System.out.println("AFTER----------------------- e.getNodeValue() "+ e.getNodeValue()+ " textContent "+textContent);
					//XMLUtilities.displayDomTree(e);
				}

				/*
				 * <w cat="P" ee="P" ei="P" lemma="de">des</w>
<w cat="A" ee="A-ind-mp" ei="Amp" lemma="tout" mph="mp" subcat="ind">tous</w>
<w cat="D" ee="D-def-mp" ei="Dmp" lemma="le" mph="mp" subcat="def"/>
<w cat="N" compound="yes" ee="N-C-mp" ei="NCmp" lemma="foies-gras" mph="mp" subcat="C">
        <w catint="N">foies</w>
        <w catint="PONCT">-</w>
        <w catint="A">gras</w>
</w>

<w cat="P" ee="P" ei="P" lemma="en">en</w>
<w cat="V" ee="V--W" ei="VW" lemma="faire" mph="W" subcat="">faire</w>
<w cat="V" ee="V--W" ei="VW" lemma="voir" mph="W" subcat="">voir</w>
<w cat="P" ee="P" ei="P" lemma="de">des</w>
<w cat="A" ee="A-ind-fp" ei="Afp" lemma="tout" mph="fp" subcat="ind">toutes</w>
<w cat="D" ee="D-def-fp" ei="Dfp" lemma="le" mph="fp" subcat="def"/>
<w cat="N" ee="N-C-fp" ei="NCfp" lemma="couleur" mph="fp" subcat="C">couleurs</w>

only two occurrences
i-2 des -> de
i -> les
				 */
				else if (isDeToutesLesSequence ( e,  nodeList,  i,  toutTextContentSet)) {
					Element eMinus2 = (Element) nodeList.item(i-2);
					eMinus2.setTextContent("de") ;
					e.setTextContent("les") ;
					/*System.out.println("isDeToutesLesSequence -----------------------");
					XMLUtilities.displayDomTree(((Element) nodeList.item(i-2)));
					XMLUtilities.displayDomTree(((Element) nodeList.item(i-1)));
					XMLUtilities.displayDomTree(((Element) nodeList.item(i)));
					XMLUtilities.displayDomTree(((Element) nodeList.item(i+1)));
					 */

				} /*else if (i>1 &&  !e.hasChildNodes()) {
					if (((Element) nodeList.item(i-1)).getTextContent().toLowerCase().trim().equalsIgnoreCase("performances")
							|| ((Element) nodeList.item(i+1)).getTextContent().toLowerCase().trim().equalsIgnoreCase("performances"))  {
						System.out.println("BEFORE----------------------- textContent "+textContent);
						//XMLUtilities.displayDomTree(((Element) nodeList.item(i-2)));
						XMLUtilities.displayDomTree(((Element) nodeList.item(i-1)));
						XMLUtilities.displayDomTree(((Element) nodeList.item(i)));
						XMLUtilities.displayDomTree(((Element) nodeList.item(i+1)));
						//XMLUtilities.displayDomTree(((Element) nodeList.item(i+1)));
					}
				}*/
				/* empty nodes two lines too late
				<w cat="N" ee="N-C-fp" ei="NCfp" lemma="tenue" mph="fp" subcat="C">tenues</w>
				<w cat="P" ee="P" ei="P" lemma="de">du</w>
				<w cat="N" ee="N-C-ms" ei="NCms" lemma="voyage" mph="ms" subcat="C">voyage</w>
				<w cat="PONCT" ee="PONCT-W" ei="PONCTW" lemma="," subcat="W">,</w>
				<w cat="D" ee="D-def-ms" ei="Dms" lemma="le" mph="ms" subcat="def"/>
				<w cat="PONCT" ee="PONCT-W" ei="PONCTW" lemma="&quot;" subcat="W">"</w>
				<w cat="ET" compound="yes" ee="ET" ei="ET" lemma="french travel">
				        <w catint="ET">french</w>
				        <w catint="ET">travel</w>
				</w>
*/
				else if (e.getAttribute(lemmaAttrName).equalsIgnoreCase("french travel")) {
					e.getParentNode().insertBefore((Element) nodeList.item(i-2), (Element) nodeList.item(i-4));
					// TODO do I need to remove it ?
				}
				/* wrong tag N -> P ; P -> D ; D -> N
				<w cat="A" ee="A-qual-ms" ei="Ams" lemma="allemand" mph="ms" subcat="qual">allemand</w>
				<w compound="yes" cat="N" ee="N-C-ms" ei="NCms" id="164" lemma="ministre des finances" mph="ms" prev="163" subcat="C">
				        <w catint="N">des</w>
				        <w catint="P"/>
				        <w catint="D">finances</w>
				</w>
*/
			}
			else {
				System.err.println("Error: the current node is not an element as espected !");
			}
			//displayDomTree(nodeList.item(i));
		}

		System.err.println("Info: # of ad hoc fix : "+adhocFixCounter+ " fixed");

	}

	/**
	 * 
	 * @param e
	 * @param textContent
	 * @return
	 */
	private Boolean isDeToutesLesSequence (Element e, NodeList nodeList, int i, Set<String> toutTextContentSet) {

		if (i>1 &&  !e.hasChildNodes() 
				&& (toutTextContentSet.contains((((Element) nodeList.item(i-1)).getTextContent().toLowerCase().trim())) )) {

			return true;
		}
		return false;
	}
	/**
	 * 
	 * @param e
	 * @param textContent
	 * @return
	 */
	private String isCompoundWithOnlyDeterminersAndEmptyElements (Element e) {
		NodeList eChildrenNodeList = e.getChildNodes();
		int emptyChildNodesCounter = 0;
		int elementNodeCounter = 0;
		int textNodeCounter = 0;
		int determinerCounter = 0;
		Boolean allEmbeddedWordsAreDeterminer = true;
		Boolean atLeastOneEmptyElement = false;
		String textContent = "";
		
		for(int j=0; (j < eChildrenNodeList.getLength()); j++) {
			// if TEXT NODE
			if (eChildrenNodeList.item(j).getNodeType() == org.w3c.dom.Node.TEXT_NODE) {
				textContent += eChildrenNodeList.item(j).getTextContent();
			}
			else if (eChildrenNodeList.item(j) instanceof Element) {
				Element eChildElement = (Element) eChildrenNodeList.item(j);

				String catVal = eChildElement.getAttribute(catAttrName);
				if (catVal.equalsIgnoreCase("")) catVal  = eChildElement.getAttribute(catintAttrName);
				if (catVal.equalsIgnoreCase(determinerTag)) determinerCounter++;
				else allEmbeddedWordsAreDeterminer = false ;
				if (!eChildElement.hasChildNodes()) {
					emptyChildNodesCounter++; 
					atLeastOneEmptyElement = true;
				}
				else {
					textContent = eChildrenNodeList.item(j).getTextContent().trim();
				}
				elementNodeCounter++;
			}
			else {}

		}
		//if ((emptyChildNodesCounter > 0) && ((elementNodeCounter == emptyChildNodesCounter) || (elementNodeCounter-1  == emptyChildNodesCounter))) {
		if (atLeastOneEmptyElement && allEmbeddedWordsAreDeterminer && (elementNodeCounter>0)) {
			/*
			<w lemma="un" ei="Dms" ee="D-ind-ms" cat="D" subcat="ind" mph="ms">un</w>
			<w lemma="&quot;" ei="PONCTW" ee="PONCT-W" cat="PONCT" subcat="W">"</w>
			<w lemma="ancrage" ei="NCms" ee="N-C-ms" cat="N" subcat="C" mph="ms">ancrage</w>
			<w lemma="&quot;" ei="PONCTW" ee="PONCT-W" cat="PONCT" subcat="W">"</w>
			<w compound="yes" lemma="de le" ei="Dms" ee="D-part-ms" cat="D" subcat="part" mph="ms">
			        <w catint="D"/>
			        <w catint="D"/>
			</w>
			<w compound="yes" lemma="taux de change" ei="NCmp" ee="N-C-mp" cat="N" subcat="C" mph="mp">
			        <w catint="N">taux</w>
			        <w catint="P">de</w>
			        <w catint="N">change</w>
			</w>
			<w lemma="." ei="PONCTS" ee="PONCT-S" cat="PONCT" subcat="S">.</w>
			</SENT>
			
			ou bien
			
			<w lemma="demander" ei="VF3s" ee="V--F3s" cat="V" subcat="" mph="F3s">demandera</w>
<w compound="yes" lemma="de le" ei="Dms" ee="D-part-ms" cat="D" subcat="part" mph="ms">
    <w catint="D"/>
    <w catint="D"/>
</w>
<w lemma="temps" ei="NCms" ee="N-C-ms" cat="N" subcat="C" mph="ms">temps</w>

			
			oubli  de la préposition 'du'
			*/	
			if (textContent.equalsIgnoreCase("")) {
				textContent = "du";
			}
			return textContent;
		}
		return "";
	}
	/**
	 * Some words part of multi words have a cat attribute instead of catint
	 * Fix that
	 * @param nodeList
	 */
	public void fixPartOfMultiWordCatAttribute (NodeList nodeList) {


		for(int i=0; (i < nodeList.getLength()); i++) {
			if (nodeList.item(i) instanceof Element) {
				Element e = (Element) nodeList.item(i);
				//if (e.hasAttribute("cat")) {
				e.setAttribute(catintAttrName, e.getAttribute(catAttrName));

				e.removeAttribute(catAttrName);
				//}
			}
			else {
				System.err.println("Error: the current node is not an element as espected !");
			}
			//displayDomTree(nodeList.item(i));
		}
		System.err.println("Info: # of PartOfMultiWord with 'cat' attribute instead of 'catint' : "+nodeList.getLength()+ " fixed");


	}

	/**
	 * coumpound attribute is missing for some multiwords 
	 * Fix that by adding compound="yes"
	 * Should also add compound="no" to be correct
	 * @param domDoc
	 */
	public void fixMultiWordCompoundAttribute (NodeList nodeList) {


		int corrected = 0;
		for(int i=0; (i < nodeList.getLength()); i++) {
			if (nodeList.item(i) instanceof Element) {
				Element e = (Element) nodeList.item(i);
				if (e.getAttribute("compound").equalsIgnoreCase("")) corrected++;
				e.setAttribute("compound", "yes");
			}
			else {
				System.err.println("Error: the current node is not an element as espected !");
			}
			//displayDomTree(nodeList.item(i));
		}
		System.err.println("Info: # of multiwords without 'compound' attribute : "+corrected+" fixed");


	}

	/**
	 * Merge amalgame words
	 *  if the previous created annotation is a prep 
	 *  case 1 : not embedded  and empty element following
	 *  <PRE>
	 *  	<w cat="P" ee="P" ei="P" lemma="à">au</w>
	 *  	<w cat="D" ee="D-def-ms" ei="Dms" lemma="le" mph="ms" subcat="def"/>
	 *  </PRE>
	 *  then it has to be corrected
	 *  otherwise the next annotation has to be corrected
	 *  case 2 : not embedded  but empty element preceding
	 *  <PRE>
	 *  	<w cat="P" ee="P" ei="P" lemma="à"/>
	 *  	<w cat="PRO" ee="PRO-rel-3mp" ei="PROR3mp" lemma="lequel" mph="3mp" subcat="rel">auxquels</w>
	 *  </PRE>					
	 *  The correction consists of modification  ftbpluscat, lemma, subcat, mph
	 *  concatenation (in the given order)
	 *  concat cat with '+' as a separator (in both elements but one can be cat and the other catint) 
	 *  concat lemma with ' ' as a separator (in both elements, but not present in part of)
	 *  concat subcat (may occurs in empty element or not ; and not present in part of mw) 
	 *  concat mph (like subcat, may occurs in empty element or not ; and not present in part of mw)
	 *  TODO
	 * Other cases
	 * partial result:
//		<w amalgame="yes" catint="P+" lemma=" le" mph="ms" subcat="def">du</w>
//		</w>
//		<w cat="D" ee="D-def-ms" ei="Dms" lemma="le" mph="ms" subcat="def"/>

//		case 3 : not the same embedded level : the empty element is following and not part of the mw 
//		<w lemma="," ei="PONCTW" ee="PONCT-W" cat="PONCT" subcat="W">,</w>
//		<w compound="yes" lemma="par l'intermédiaire de" ei="P" ee="P" cat="P">
//		        <w catint="P">par</w>
//		        <w catint="D">l'</w>
//		        <w catint="N">intermédiaire</w>
//		        <w catint="P">du</w>
//		</w>
//		<w lemma="le" ei="Dms" ee="D-def-ms" cat="D" subcat="def" mph="ms"/>
//		<w lemma="crédit" ei="NCms" ee="N-C-ms" cat="N" subcat="C" mph="ms">Crédit</w>
//		<w lemma="suisse" ei="Ams" ee="A-qual-ms" cat="A" subcat="qual" mph="ms">suisse</w>
//
//		cas : idem		
//		<w compound="yes" lemma="au sein de" ei="P" ee="P" cat="P">
//			<w>Au</w>
//			<w catint="N">sein</w>
//			<w catint="P">du</w>
//		</w>
//		<w lemma="le" ei="Dms" ee="D-def-ms" cat="D" subcat="def" mph="ms"/>
//		<w lemma="système" ei="NCms" ee="N-C-ms" cat="N" subcat="C" mph="ms">système</w>
//		
//		case 4 : not the same embedded level : the empty element is following and is part of the mw
// 		<w lemma="à" ei="P" ee="P" cat="P">au</w>
//		<w compound="yes" lemma="le plus" ei="ADV" ee="ADV" cat="ADV">
//        <w catint="D"/>
//        <w catint="ADV">plus</w>
//		</w>
//		<w lemma="haut" ei="Ams" ee="A-qual-ms" cat="A" subcat="qual" mph="ms">haut</w>
//
//		cas : idem
//		<w lemma="tout" ei="ADV" ee="ADV" cat="ADV">tout</w>
//		<w lemma="à" ei="P" ee="P" cat="P">au</w>
//		<w compound="yes" lemma="le moins" ei="ADV" ee="ADV" cat="ADV">
//		        <w catint="D"/>
//		        <w catint="ADV">moins</w>
//		</w>
	 * 	
	 * 		may exist two other cases : 
	 * //		case 5 : not the same embedded level : the empty element is preceding and is not part of the mw
	 * 
	 * 
	 * 
	 * since lequel not possible to be part of mw, this case does not exist 
   //		case 6 : not the same embedded level : the empty element is preceding and is part of the mw
	 * <w cat="PRO" ee="PRO-dem-3fp" ei="PRO3fp" lemma="celles" mph="3fp" subcat="dem">celles</w>
<w compound="yes" cat="P" ee="P" ei="P" lemma="à raison de">
        <w catint="P">à</w>
        <w catint="N">raison</w>
        <w catint="P"/>
</w>
<w cat="PRO" ee="PRO-rel-3fp" ei="PROR3fp" lemma="lesquelles" mph="3fp" subcat="rel">desquelles</w>

<w compound="yes" lemma="à propos de" ei="P" ee="P" cat="P">
        <w catint="P">à</w>
        <w catint="N">propos</w>
        <w catint="P"/>
</w>
<w lemma="lequel" ei="PROR3fp" ee="PRO-rel-3fp" cat="PRO" subcat="" mph="3fp">desquelles</w>

//
	 * 
	 * <w lemma="au sein de" ei="P" ee="P" cat="P">
<w>au</w>
        <w catint="N">sein</w>
<w>duquel</w>
</w>
<w lemma="lequel" ei="PROR3ms" ee="PRO-rel-3ms" cat="PRO" subcat="rel" mph="3ms"/>

	 * 
	 * 	 *  case 7 both embedded and empty following ; both may have catint value or not, no lemma, no subcat, no mph 
	 *  <w compound="yes" lemma="au-dessous de" ei="P" ee="P" cat="P">
        <w catint="P">au</w>
        <w catint="D"/>
        <w catint="PONCT">-</w>
        <w catint="ADV">dessous</w>
        <w catint="P">de</w>
</w>
	 * 		case 8: like 3 but without catint value...
	 * <w lemma="octroyer" ei="VKmp" ee="V--Kmp" cat="V" subcat="" mph="Kmp">octroyés</w>
<w compound="yes" lemma="par de" ei="P" ee="P" cat="P">
        <w catint="">par</w>
        <w catint="">des</w>
</w>
<w lemma="le" ei="Dfp" ee="D-def-fp" cat="D" subcat="def" mph="fp"/>
<w lemma="banque" ei="NCfp" ee="N-C-fp" cat="N" subcat="C" mph="fp">banques</w>

As a consequence some attributes absent until now can be present in mw
 <w cat="P" compound="yes" ee="P" ei="P" lemma="par de">
        <w catint="">par</w>
        <w amalgame="yes" catint="P+D" lemma="de le" mph="fp" subcat="def">des</w>
</w>
		// idem with "au"
<w lemma="," ei="PONCTW" ee="PONCT-W" cat="PONCT" subcat="W">,</w>
<w compound="yes" lemma="par opposition à" ei="P" ee="P" cat="P">
        <w catint="">par</w>
        <w catint="">opposition</w>
        <w catint="">au</w>
</w>
<w lemma="le" ei="Dms" ee="D-def-ms" cat="D" subcat="def" mph="ms"/>
<w lemma="secteur" ei="NCms" ee="N-C-ms" cat="N" subcat="C" mph="ms">secteur</w>

	case 9 :
<w lemma="expliquer" ei="VP3s" ee="V--P3s" cat="V" subcat="" mph="P3s">explique</w>
<w compound="yes" lemma="il" ei="CL3ms" ee="CL-suj-3ms" cat="CL" subcat="suj" mph="3ms">
        <w catint=""/>
        <w catint="PONCT">-</w>
        <w catint="">t</w>
        <w catint="PONCT">-</w>
        <w catint="">il</w>
</w>

// idem but with cat bug instead of catint
<w lemma="il" ei="CL3ms" ee="CL-suj-3ms" cat="CL" subcat="suj" mph="3ms">
<w cat=""/>
<w cat="PONCT">-</w>
<w cat="">t</w>
<w cat="PONCT">-</w>
<w cat="">il</w>

case 10: characterized by the absence of catint attribute
<w lemma="au sein de" ei="P" ee="P" cat="P">
	<w>au</w>
    <w catint="N">sein</w>
	<w>duquel</w>
</w>
<w lemma="lequel" ei="PROR3ms" ee="PRO-rel-3ms" cat="PRO" subcat="rel" mph="3ms"/>
<w lemma="TCE" ei="NPs" ee="N-P-ms" cat="N" subcat="P" mph="ms">TCE</w>
<w lemma="devoir" ei="VP3s" ee="V--P3s" cat="V" subcat="" mph="P3s">doit</w>


<w amalgame="yes" cat="D+N" ee="N-C-ms" ei="NCms" lemma="le contrat" mph="msms" subcat="defC">contrat</w>


</w>
we remove it since there is no information

case 
<w cat="V" ee="V--P3p" ei="VP3p" lemma="être" mph="P3p" subcat="">sont</w>
<w compound="yes" cat="D" ee="D-ind-mp" ei="Dmp" lemma="de les" mph="mp" subcat="ind">des       <w catint="D"/>
        <w catint="D"/>
</w>
<w cat="N" ee="N-C-mp" ei="NCmp" lemma="ayatollah" mph="mp" subcat="C">ayatollahs</w>

<w cat="V" ee="V--W" ei="VW" lemma="provoquer" mph="W" subcat="">provoquer</w>
<w compound="yes" cat="D" ee="D-ind-fp" ei="Dfp" lemma="de les" mph="fp" subcat="ind">des       <w catint="D"/>
        <w catint="D"/>
</w>
<w cat="N" ee="N-C-fp" ei="NCfp" lemma="trêve" mph="fp" subcat="C">trêves</w>

<w lemma="il y a" ei="P" ee="P" cat="P">
<w cat="CL">il</w>
<w cat="CL">y</w>
<w cat="V">a</w>
</w>
<w lemma="un" ei="Dmp" ee="D-ind-mp" cat="D" subcat="ind" mph="mp">
<w cat="D">des</w>
<w cat="D"/>
</w>
<w lemma="scénariste" ei="NCmp" ee="N-C-mp" cat="N" subcat="C" mph="mp">scénaristes</w>
<w lemma="," ei="PONCTW" ee="PONCT-W" cat="PONCT" subcat="W">,</w>
<w lemma="un" ei="Dmp" ee="D-ind-mp" cat="D" subcat="ind" mph="mp">
<w cat="D">des</w>
<w cat="D"/>
</w>
<w lemma="éclairagiste" ei="NCmp" ee="N-C-mp" cat="N" subcat="C" mph="mp">éclairagistes</w>

case

ancêtre</w>
<w cat="P" ee="P" ei="P" lemma="de">des</w>
<w cat="A" ee="A-ind-mp" ei="Amp" lemma="tout" mph="mp" subcat="ind">tous</w>
<w cat="D" ee="D-def-mp" ei="Dmp" lemma="le" mph="mp" subcat="def"/>
<w cat="N" compound="yes" ee="N-C-mp" ei="NCmp" lemma="foies-gras" mph="mp" subcat="C">
        <w catint="N">foies</w>
        <w catint="PONCT">-</w>
        <w catint="A">gras</w>
</w>

<w cat="P" ee="P" ei="P" lemma="en">en</w>
<w cat="V" ee="V--W" ei="VW" lemma="faire" mph="W" subcat="">faire</w>
<w cat="V" ee="V--W" ei="VW" lemma="voir" mph="W" subcat="">voir</w>
<w cat="P" ee="P" ei="P" lemma="de">des</w>
<w cat="A" ee="A-ind-fp" ei="Afp" lemma="tout" mph="fp" subcat="ind">toutes</w>
<w cat="D" ee="D-def-fp" ei="Dfp" lemma="le" mph="fp" subcat="def"/>
<w cat="N" ee="N-C-fp" ei="NCfp" lemma="couleur" mph="fp" subcat="C">couleurs</w>


<w cat="V" ee="V--P3s" ei="VP3s" lemma="être" mph="P3s" subcat="">est</w>
<w cat="CL" ee="CL-suj-3ms" ei="CLS3ms" lemma="ce" mph="3ms" subcat="suj">-ce</w>
<w cat="D" ee="D-part-ms" ei="Dms" lemma="du" mph="ms" subcat="part"/>
<w cat="N" ee="N-C-ms" ei="NCms" lemma="cynisme" mph="ms" subcat="C">cynisme</w>

case " entre P et empty node
<w cat="V" ee="V--Kms" ei="VKms" lemma="établir" mph="Kms" subcat="">établi</w>
<w cat="P" compound="yes" ee="P" ei="P" lemma="à partir de">
        <w catint="P">à</w>
        <w catint="V">partir</w>
        <w catint="P">des</w>
</w>
<w cat="PONCT" ee="PONCT-W" ei="PONCTW" lemma="&quot;" subcat="W">"</w>
<w cat="D" ee="D-def-fp" ei="Dfp" lemma="le" mph="fp" subcat="def"/>
<w cat="N" ee="N-C-fp" ei="NCfp" lemma="hypothèse" mph="fp" subcat="C">hypothèses</w>
<w cat="V" ee="V--Kfp" ei="VKfp" lemma="considérer" mph="Kfp" subcat="">considérées</w>
<w cat="P" ee="P" ei="P" lemma="comme">comme</w>
<w cat="D" ee="D-def-fp" ei="Dfp" lemma="le" mph="fp" subcat="def">les</w>
<w cat="ADV" ee="ADV" ei="ADV" lemma="plus">plus</w>
<w cat="A" ee="A-qual-fp" ei="Afp" lemma="probable" mph="fp" subcat="qual">probables</w>
<w cat="PONCT" ee="PONCT-W" ei="PONCTW" lemma="&quot;" subcat="W">"</w>

case 
<w cat="V" ee="V--Kms" ei="VKms" lemma="diffuser" mph="Kms" subcat="">diffusé</w>
<w cat="P" ee="P" ei="P" lemma="en">en</w>
<w cat="N" ee="N-card-fs" ei="NCfs" lemma="1990" mph="fs" subcat="card">1990</w>
<w cat="D" ee="D-ind-fp" ei="Dfp" lemma="un" mph="fp" subcat="ind">des</w>
<w cat="D" ee="D-def-fp" ei="Dfp" lemma="le" mph="fp" subcat="def"/>
<w cat="PONCT" ee="PONCT-W" ei="PONCTW" lemma="&quot;" subcat="W">"</w>
<w cat="N" ee="N-C-fp" ei="NCfp" lemma="information" mph="fp" subcat="C">informations</w>

cet empty est une erreur selon moi
attention difficile à corriger par observation du D qui précède qui semble correct
seach determinerTag dans le code pour d'autres exemples

        TODO revoir lemma 'à' -> 'à le', 'de' -> 'de le', auprès 
<w amalgame="yes" catint="P+D" ee="P+D--" ei="P+D" lemma="de">des</w>
<w amalgame="yes" catint="P+D" ee="P+D--" ei="P+D" lemma="de">du</w>
<w amalgame="yes" catint="P+P" ee="P+P--" ei="P+P" lemma="">auprès</w>

TODO to check if there are bugs remaining less /tmp/domoutfile-light-revised.xml | grep '+' 
	 *          
	 * @param domDoc
	 */
	public void fixAmalgame (NodeList nodeList) {
		System.err.println("Info: dom xpath evaluation done");
		Map<String,String> futureLastWordFeaturesMap = null ;
		final String duLemmaString  = "de";
		Set<String> deTextContentSet = new HashSet<String>();
		deTextContentSet.add("d'");	
		deTextContentSet.add("de");	
		deTextContentSet.add("des");
		deTextContentSet.add("du");	
		deTextContentSet.add("des");	
		deTextContentSet.add("du");

		final String aLemmaString  ="à";
		Set<String> aTextContentSet = new HashSet<String>();
		aTextContentSet.add("a"); 
		aTextContentSet.add("à"); 
		//aTextContentSet.add("À");
		aTextContentSet.add("au");	
		aTextContentSet.add("aux");
		//System.out.println("Debug À :"+ ("À".toLowerCase()));
		//System.out.println("Debug AUX :"+ ("AUX".toLowerCase()));

		final String lequelLemmaString  ="lequel";
		Set<String> lequelTextContentSet = new HashSet<String>();
		lequelTextContentSet.add("à"); 
		lequelTextContentSet.add("auquel");
		lequelTextContentSet.add("auxquelles");
		lequelTextContentSet.add("auxquels");
		lequelTextContentSet.add("desquelles");
		lequelTextContentSet.add("desquels");
		lequelTextContentSet.add("duquel");
		lequelTextContentSet.add("laquelle");
		lequelTextContentSet.add("lequel");
		lequelTextContentSet.add("lesquelles");
		lequelTextContentSet.add("lesquels");

		int corrected = 0;	

		for(int i=0; (i < nodeList.getLength()); i++) {
			if (nodeList.item(i) instanceof Element) {
				Element currentE = (Element) nodeList.item(i);

				//isEmptyElement
				//NodeList fils = e.getChildNodes();
				//if (fils.getLength() != 0) {
				//}
				// is part of amalgame
				// but we do not know if is part of mw and if the main part is prior or next and if it is part of mw
				if (!currentE.hasChildNodes()) {

					//TODO strong assumption : the first word is not an amalgame (avoid a test)
					Element previousE = (Element) nodeList.item(i-1);
					String previousTextContent = previousE.getTextContent().trim().toLowerCase();
					/*
					 * 
case " entre P et empty node
<w cat="V" ee="V--Kms" ei="VKms" lemma="établir" mph="Kms" subcat="">établi</w>
<w cat="P" compound="yes" ee="P" ei="P" lemma="à partir de">
        <w catint="P">à</w>
        <w catint="V">partir</w>
        <w catint="P">des</w>
</w>
<w cat="PONCT" ee="PONCT-W" ei="PONCTW" lemma="&quot;" subcat="W">"</w>
<w cat="D" ee="D-def-fp" ei="Dfp" lemma="le" mph="fp" subcat="def"/>
<w cat="N" ee="N-C-fp" ei="NCfp" lemma="hypothèse" mph="fp" subcat="C">hypothèses</w>
<w cat="V" ee="V--Kfp" ei="VKfp" lemma="considérer" mph="Kfp" subcat="">considérées</w>
<w cat="P" ee="P" ei="P" lemma="comme">comme</w>
<w cat="D" ee="D-def-fp" ei="Dfp" lemma="le" mph="fp" subcat="def">les</w>
<w cat="ADV" ee="ADV" ei="ADV" lemma="plus">plus</w>
<w cat="A" ee="A-qual-fp" ei="Afp" lemma="probable" mph="fp" subcat="qual">probables</w>
<w cat="PONCT" ee="PONCT-W" ei="PONCTW" lemma="&quot;" subcat="W">"</w>


*/
					
					if (previousTextContent.equalsIgnoreCase("\"")) {
						previousE = (Element) nodeList.item(i-2);
					}
					
					Boolean previousIsPartOf = false;
					//if (previousE.hasAttribute(catintAttrName)) previousIsPartOf = true;
					// since some w element does not have cat or catint attributes...
					Element p = (Element)previousE.getParentNode();
					// Both give the same
					// System.out.println("Debug: p.getNodeName() "+ p.getNodeName()+ " p.getTagName() "+ p.getTagName());


					if (previousE == null) System.out.println("Debug: previousE == null");
					if (p == null) System.out.println("Debug: parrentPreviousE == null (may be it is because it is considered as an element and should be a node)");

					// some case where empty element starts a sentence
					// and consequently its p is null ?
					if (p != null) { 
						String t = p.getNodeName();

						//System.out.println("Debug: previousE.getTextContent "+ previousE.getTextContent());

						//if (previousE.hasAttribute(catintAttrName)) previousIsPartOf = true;

						if (t.equalsIgnoreCase(wordElement)) previousIsPartOf = true;


						Boolean currentIsPartOf = false;
						//if (currentE.hasAttribute(catintAttrName)) currentIsPartOf = true;
						// since some w element does not have cat or catint attributes...
						if (((Element)currentE.getParentNode()).getTagName().equalsIgnoreCase(wordElement)) currentIsPartOf = true;

						String previousCatAttrName = catAttrName;
						if (previousIsPartOf) previousCatAttrName = catintAttrName;

						String currentCatAttrName = catAttrName;
						if (currentIsPartOf) currentCatAttrName = catintAttrName;

						Boolean isCurrentAndPreviousTheSameEmbeddedLevel = previousCatAttrName.equalsIgnoreCase(currentCatAttrName) ? true : false;
						Boolean areBothEmbedded = (previousIsPartOf && currentIsPartOf);

						
						String previousECatValue	= previousE.getAttribute (previousCatAttrName).trim();
						String previousELemmaValue	= previousE.getAttribute (lemmaAttrName).trim();
						String previousESubcatValue	= previousE.getAttribute (subcatAttrName).trim();
						String previousESMphValue	= previousE.getAttribute (mphAttrName).trim();

						//String currentETextContent	= currentE.getTextContent().trim().toLowerCase();
						String currentECatValue	= currentE.getAttribute (currentCatAttrName).trim();
						String currentELemmaValue	= currentE.getAttribute (lemmaAttrName).trim();
						String currentESubcatValue	= currentE.getAttribute (subcatAttrName).trim();
						String currentEMphValue	= currentE.getAttribute (mphAttrName).trim();
						int currentEAttributeLength = currentE.getAttributes().getLength();
						//if (areBothEmbedded) System.err.println("Debug: previousECatValue "+previousECatValue+" currentECatValue "+currentECatValue);

						//  do not consider such line      <w catint=""/> 
						if (!((currentEAttributeLength == 1) && (currentECatValue.equalsIgnoreCase("")))) {


							// if not in the same depth
							if ((!isCurrentAndPreviousTheSameEmbeddedLevel) || areBothEmbedded) {
								if (previousIsPartOf) {
									if (deTextContentSet.contains(previousTextContent)) previousELemmaValue = duLemmaString;
									else if (aTextContentSet.contains(previousTextContent)) previousELemmaValue = aLemmaString;
									else if (lequelTextContentSet.contains(previousTextContent)) previousELemmaValue = lequelLemmaString;
									/*
									 * <w cat="P" compound="yes" ee="P" ei="P" lemma="au-delà de">
        <w catint="P">Au</w>
        <w catint="D"/>
        <w catint="PONCT">-</w>
        <w catint="ADV">delà</w>
        <w catint="D">des</w>
</w>
<w cat="D" ee="D-def-fp" ei="Dfp" lemma="le" mph="fp" subcat="def"/>
<w cat="N" ee="N-C-fp" ei="NCfp" lemma="performance" mph="fp" subcat="C">performances</w>


<w cat="V" ee="V--Kms" ei="VKms" lemma="diffuser" mph="Kms" subcat="">diffusé</w>
<w cat="P" ee="P" ei="P" lemma="en">en</w>
<w cat="N" ee="N-card-fs" ei="NCfs" lemma="1990" mph="fs" subcat="card">1990</w>
<w cat="D" ee="D-ind-fp" ei="Dfp" lemma="un" mph="fp" subcat="ind">des</w>
<w cat="D" ee="D-def-fp" ei="Dfp" lemma="le" mph="fp" subcat="def"/>
<w cat="PONCT" ee="PONCT-W" ei="PONCTW" lemma="&quot;" subcat="W">"</w>
<w cat="N" ee="N-C-fp" ei="NCfp" lemma="information" mph="fp" subcat="C">informations</w>

fix also when they are at the same depth
at the same level and not embedded, not easy to merge - either we merge but we have to handle duplicate information
or we decline one : the former ?
									 */
									if ((previousECatValue.equalsIgnoreCase("") || (previousECatValue.equalsIgnoreCase(determinerTag)))
											&&  (deTextContentSet.contains(previousTextContent) 
													|| aTextContentSet.contains(previousTextContent) 
													|| lequelTextContentSet.contains(previousTextContent))) previousECatValue = prepositionTag;
								}
								// means currentIsPartOf
								else {

								}
							}

							// case 1: if the previous created annotation is a prep 
							//<w cat="P" ee="P" ei="P" lemma="à">au</w>
							//<w cat="D" ee="D-def-ms" ei="Dms" lemma="le" mph="ms" subcat="def"/>
							// 
							//					case 3 : not the same embedded level : the empty element is following and not part of the mw 
							//					<w lemma="," ei="PONCTW" ee="PONCT-W" cat="PONCT" subcat="W">,</w>
							//					<w compound="yes" lemma="par l'intermédiaire de" ei="P" ee="P" cat="P">
							//					        <w catint="P">par</w>
							//					        <w catint="D">l'</w>
							//					        <w catint="N">intermédiaire</w>
							//					        <w catint="P">du</w>
							//					</w>
							//					<w lemma="le" ei="Dms" ee="D-def-ms" cat="D" subcat="def" mph="ms"/>
							//
							//					case 4 : not the same embedded level : the empty element is following and is part of the mw
							//			 		<w lemma="à" ei="P" ee="P" cat="P">au</w>
							//					<w compound="yes" lemma="le plus" ei="ADV" ee="ADV" cat="ADV">
							//			        	<w catint="D"/>
							//			        	<w catint="ADV">plus</w>
							//					</w>
							if (previousECatValue.equalsIgnoreCase(prepositionTag) ) {
								// then it has to be corrected

								String catCorrection = "";
								catCorrection = (previousECatValue + "+" + currentECatValue).trim();  

								String lemmaCorrection = "";
								if (!previousELemmaValue.trim().equalsIgnoreCase(currentELemmaValue.trim()))
									lemmaCorrection = (previousELemmaValue + " " + currentELemmaValue).trim();
								else
									lemmaCorrection = previousELemmaValue.trim();

								String subcatCorrection = "";
								subcatCorrection = (previousESubcatValue + currentESubcatValue).trim();

								String mphCorrection = "";
								mphCorrection = (previousESMphValue + currentEMphValue).trim();

								String eeCorrection = "";
								eeCorrection = (catCorrection+"-"+subcatCorrection+"-"+mphCorrection ).trim();

								String eiCorrection = "";
								eiCorrection = (catCorrection+subcatCorrection+mphCorrection ).trim();

								// modification  ftbpluscat, lemma, subcat, mph
								previousE.setAttribute(previousCatAttrName, catCorrection);
								previousE.setAttribute(lemmaAttrName, lemmaCorrection);
								if (!subcatCorrection.equalsIgnoreCase("")) previousE.setAttribute(subcatAttrName, subcatCorrection);
								if (!mphCorrection.equalsIgnoreCase("")) previousE.setAttribute(mphAttrName, mphCorrection);
								previousE.setAttribute("amalgame","yes");

								previousE.setAttribute(eeAttrName,eeCorrection);
								previousE.setAttribute(eiAttrName,eiCorrection);

								corrected++;

								// print previous word tag created after modification
								//System.out.println("Debug: lastFTVWord"+ lastFTVWord);
							}
							// otherwise the next annotation to create has to be corrected
							// case 2 : same embedded level but empty element preceding
							// <w cat="P" ee="P" ei="P" lemma="à"/>
							// <w cat="PRO" ee="PRO-rel-3mp" ei="PROR3mp" lemma="lequel" mph="3mp" subcat="rel">auxquels</w>
							//	
							// case 6: 
							// <w cat="PRO" ee="PRO-dem-3fp" ei="PRO3fp" lemma="celles" mph="3fp" subcat="dem">celles</w>
							// <w compound="yes" cat="P" ee="P" ei="P" lemma="à raison de">
							//		<w catint="P">à</w>
							//		<w catint="N">raison</w>
							//		<w catint="P"/>
							// </w>
							// <w cat="PRO" ee="PRO-rel-3fp" ei="PROR3fp" lemma="lesquelles" mph="3fp" subcat="rel">desquelles</w>

							else {
								futureLastWordFeaturesMap = new HashMap<String,String>();
								futureLastWordFeaturesMap.put(currentCatAttrName, currentE.getAttribute(currentCatAttrName));
								futureLastWordFeaturesMap.put(lemmaAttrName, currentE.getAttribute(lemmaAttrName));
								futureLastWordFeaturesMap.put(subcatAttrName, currentE.getAttribute(subcatAttrName));
								futureLastWordFeaturesMap.put(mphAttrName, currentE.getAttribute(mphAttrName));

							}
						}
					}
					//else {System.out.println ("Debug: current E catAttribute "+currentECatValue+ " currentEAttributeLength "+currentEAttributeLength);}
					//
					currentE.getParentNode().removeChild(currentE);

				}
				else {
					// it is a simple word which is not part of an amalgame
					Boolean isPartOf = false;
					if (currentE.hasAttribute(catintAttrName)) isPartOf = true;

					String currentCatAttrName = catAttrName;
					if (isPartOf) currentCatAttrName = catintAttrName;


					// if the previous word tag was part of an amalgame 
					if (futureLastWordFeaturesMap != null) {
						// correct the current word before creation		

						String previousCatAttrValue = "";
						if (futureLastWordFeaturesMap.containsKey(catAttrName)) previousCatAttrValue =  futureLastWordFeaturesMap.get(catAttrName);
						else previousCatAttrValue = futureLastWordFeaturesMap.get(catintAttrName);

						String catCorrection = "";
						catCorrection = (previousCatAttrValue + "+" + currentE.getAttribute(currentCatAttrName)).trim();  

						String lemmaCorrection = "";
						lemmaCorrection = (futureLastWordFeaturesMap.get(lemmaAttrName) + " " + currentE.getAttribute(lemmaAttrName)).trim();

						String subcatCorrection = "";
						subcatCorrection = (futureLastWordFeaturesMap.get(subcatAttrName) + "" +  currentE.getAttribute(subcatAttrName)).trim();

						String mphCorrection = "";
						mphCorrection = (futureLastWordFeaturesMap.get(mphAttrName) + "" +  currentE.getAttribute(mphAttrName)).trim();


						currentE.setAttribute(catAttrName, catCorrection	);
						currentE.setAttribute(lemmaAttrName, lemmaCorrection	);
						if (!subcatCorrection.equalsIgnoreCase("")) currentE.setAttribute(subcatAttrName, subcatCorrection	);
						if (!mphCorrection.equalsIgnoreCase(""))  currentE.setAttribute(mphAttrName, mphCorrection	);
						currentE.setAttribute("amalgame","yes");

						String eeCorrection = "";
						eeCorrection = (catCorrection+"-"+subcatCorrection+"-"+mphCorrection ).trim();

						String eiCorrection = "";
						eiCorrection = (catCorrection+subcatCorrection+mphCorrection ).trim();

						currentE.setAttribute(eeAttrName,eeCorrection);
						currentE.setAttribute(eiAttrName,eiCorrection);

						//
						corrected++;

						// re init
						futureLastWordFeaturesMap = null;
					}
				}

			}
			else {
				System.err.println("Error: the current node is not an element as espected !");
			}
			//displayDomTree(nodeList.item(i));
		}
		System.err.println("Info: # of amalgame : "+corrected+" fixed");


	}



	/*
	 * MAIN 
	 */

	/**
	 * 
	 */
	public static void usage () {
		System.err.println("Usage: java programName <source> <target>");
	}

	/**
	 * 
	 * @param args
	 * @throws Exception
	 */
	public static void main(String[] args) throws Exception {

		if (args.length != 2) {
			usage();
			System.err.println("Wrong number of parameter");
			return;}

		Date currentDate = DateUtilities.getNow();
		Date startDate = currentDate;
		System.err.println("Info: L> Start processing "+ DateUtilities.stringFormatADate(currentDate));
		System.err.println("Info: -------------------------------------------------------------------------");

		FTBProcessRevision aFTBCleaner = new FTBProcessRevision();

		aFTBCleaner.infileName = args[0];
		aFTBCleaner.outfileName = args[1];


		// Import XML File to DOM
		aFTBCleaner.domDoc = XMLUtilities.readXMLFile2Dom (aFTBCleaner.infileName );

		Date previousDate = currentDate;
		currentDate = DateUtilities.getNow();
		System.err.println("Info: L> Import XML File to DOM "+ DateUtilities.dateDiff(previousDate,currentDate)+ " ms");
		System.err.println("Info: -------------------------------------------------------------------------");

		// perform some adhoc fix
		aFTBCleaner.adhocFix (aFTBCleaner.domDoc);
		previousDate = currentDate;
		currentDate = DateUtilities.getNow(); 
		System.err.println("Info: L> Perform ad hoc local fix "+ DateUtilities.dateDiff(previousDate,currentDate)+ " ms");
		System.err.println("Info: -------------------------------------------------------------------------");

		// Revise fixPartOfMultiWordCatAttribute
		NodeList partOfMWWiCatAttributeNodeList  = FTBXMLVariousDOMHandler.getNodeListFromXPathExpression(aFTBCleaner.domDoc,FTBXMLVariousDOMHandler.partOfMWWiCatAttributeXPathExpression);
		aFTBCleaner.fixPartOfMultiWordCatAttribute(partOfMWWiCatAttributeNodeList);
		//partOfMWWiCatAttributeNodeList = null; System.gc();
		previousDate = currentDate;
		currentDate = DateUtilities.getNow();
		System.err.println("Info: L> Turn partOfMultiWord word cat attribute into catint "+ DateUtilities.dateDiff(previousDate,currentDate)+ " ms");
		System.err.println("Info: -------------------------------------------------------------------------");

		//
		NodeList mWWiCompoundAttributeMissionNodeList  = FTBXMLVariousDOMHandler.getNodeListFromXPathExpression(aFTBCleaner.domDoc,FTBXMLVariousDOMHandler.mWWiCompoundAttributeMissionXPathexpression);
		aFTBCleaner.fixMultiWordCompoundAttribute(mWWiCompoundAttributeMissionNodeList);
		//mWWiCompoundAttributeMissionNodeList = null; System.gc();
		previousDate = currentDate;
		currentDate = DateUtilities.getNow();
		System.err.println("Info: L> Add missing multi word compound attribute "+ DateUtilities.dateDiff(previousDate,currentDate)+ " ms");
		System.err.println("Info: -------------------------------------------------------------------------");

		//
		NodeList notAMWNodeList  = FTBXMLVariousDOMHandler.getNodeListFromXPathExpression(aFTBCleaner.domDoc,FTBXMLVariousDOMHandler.notAMWXPathExpression);
		aFTBCleaner.fixAmalgame(notAMWNodeList);
		previousDate = currentDate;
		currentDate = DateUtilities.getNow();
		System.err.println("Info: L> Merge Amalgame "+ DateUtilities.dateDiff(previousDate,currentDate)+ " ms");
		System.err.println("Info: -------------------------------------------------------------------------");

		// Export  DOM 2 XML
		XMLUtilities.writeDOM2XMLFile (aFTBCleaner.domDoc,aFTBCleaner.outfileName);

		previousDate = currentDate;
		currentDate = DateUtilities.getNow();
		System.err.println("Info: L> Export DOM 2 XML "+ DateUtilities.dateDiff(previousDate,currentDate)+ " ms");

		System.err.println("Info: -------------------------------------------------------------------------");
		System.err.println("Info: L> Total time "+ DateUtilities.dateDiff(startDate,currentDate)+ " ms");
		System.err.println("Info: -------------------------------------------------------------------------");

		//System.out.println("<?xml version=\"" +domDoc.getXmlVersion()+ "\" encoding=\""+domDoc.getXmlEncoding() + "\"?>");
		//display("", domDoc);
	}
}